﻿// ***********************************************************************
// Assembly         : SecurityLayer
// Author           : LJO+01 (Laurent Jordi)
// Created          : 06-05-2013
// Last Modified By : LJO+01 (Laurent Jordi)
// Last Modified On : 06-05-2013
// ***********************************************************************
// <copyright file="RegisterController.cs" company="Copyright © Innovacall 2011">
//     Copyright (c) Copyright © Innovacall 2011. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Transactions;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using InnovaApp.Layers.DataLayer;
using InnovaApp.Layers.DomainLayer;
using InnovaApp.Layers.ResourcesLayer.Properties;
using InnovaApp.Layers.SecurityLayer.Models;
using InnovaApp.Layers.SecurityLayer.Models.AccountModels.MembershipServices;
using InnovaApp.Layers.SecurityLayer.Models.ViewModels._LayoutViewModels;
using INNOVACALL.Framework.Common;
using INNOVACALL.Framework.Common.Logging;
using InnovaApp.Layers.CommonLayer;
using InnovaApp.Portals.MVC4Portal.Models.ViewModels.LayoutViewModels.SecurityViewModels;
using INNOVACALL.Framework.Common.MVCHelpers.Localization;
using INNOVACALL.Framework.Common.MVCHelpers;

namespace InnovaApp.Portals.MVC4Portal.Controllers.ViewControllers.LayoutViewControllers.SecurityControllers
{
    /// <summary>
    /// Class RegisterController
    /// </summary>
    public class RegisterController : _SecurityControllers_Base<Register_ViewModel>
    {
        /// <summary>
        /// Gets or sets the forms service.
        /// </summary>
        /// <value>The forms service.</value>
        public IFormsAuthenticationService FormsService { get; set; }
        /// <summary>
        /// Gets or sets the membership service.
        /// </summary>
        /// <value>The membership service.</value>
        public IMembershipService MembershipService { get; set; }

        /// <summary>
        /// Initializes data that might not be available when the constructor is called.
        /// </summary>
        /// <param name="requestContext">The HTTP context and route data.</param>
        protected override void Initialize(RequestContext requestContext)
        {
            base.eMethodBase = "InnovaApp.Layers.SecurityLayer.Controllers.RegisterController";
            base.specificCssCollection = new string[] { "Views/Account/AccountCommon.css", "ClientComponents/KendoUI/kendo." + PortalEnvironment.KendoUITheme + ".min.css" };
            base.specificJSCollection = null;
            base.dynamicJSCollection = new string[] { "/ScriptsG/RegisterDynamic.js" };
            base.specificJqueryJSCollection = new string[] { "Views/Register.js", "JSonModels/JSonModelsMenuEdition1.js" };

            base.externalCss = null;
            base.Meta.Add(enMeta.Description, Resources.View_Register_Meta_Description);
            base.Meta.Add(enMeta.Keywords, Resources.View_Register_Meta_Keywords);
            base.Meta.Add(enMeta.Subject, Resources.View_Register_Meta_Subject);

            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        #region Register

        /// <summary>
        /// URL[Get]: /Register
        /// </summary>
        /// <returns>ActionResult.</returns>
        [AllowAnonymous, HttpGet]
        public ActionResult Index()
        {
            string eMethod = eMethodBase + ".Index[GET]";
            string language = base.URLReferLanguage;
            base.LocalizeDynamicScript(language, (CurrentContact != null ? CurrentContact.FavoriteLanguage.Language : null));

            using (DataRepositories _dataContext = new DataRepositories())
            {
                base.InitView(
                    pageTitle: Resources.View_Register_PageTitle,
                    openingMessage: string.Empty,
                    specificCssCollection: specificCssCollection,
                    specificJSCollection: specificJSCollection,
                    dynamicJSCollection: dynamicJSCollection,
                    specificJqueryJSCollection: specificJqueryJSCollection,
                    jsVariables: jsVariables,
                    externalJs: externalJs,
                    externalCss: externalCss,
                    metaToAdd: Meta,
                    _dataContext: _dataContext,
                    displayMenus: false,
                    language: language,
                    adminMode: false,
                    usesKendoUI: true,
                    jQueryUITheme: null,
                    kendoUITheme: null,
                    currentUser: Membership.GetUser()
                    );

                ContentData.Contact.Genres = GetGenres(_dataContext, language);
                ContentData.Contact.Languages = GetLanguages(_dataContext, language);
            }
            return View(ContentData);
        }

        /// <summary>
        /// Gets the languages.
        /// </summary>
        /// <param name="_dataContext">The _data context.</param>
        /// <param name="language">The language.</param>
        /// <returns>List{SelectListItem}.</returns>
        private List<SelectListItem> GetLanguages(DataRepositories _dataContext, string language)
        {
            List<Language> dbLanguages = _dataContext.Language_Rep.GetAll().OrderBy(x => x.Name).ToList();
            List<SelectListItem> toReturn = dbLanguages.Select(x => new SelectListItem() { Value = x.Id.ToString(), Text = INNOVACALL.Framework.Common.MVCHelpers.Localization.CommonLocalization.LookupResource(typeof(Resources), string.Format("View_All_Languages_{0}", x.Name)), Selected = (x.Id == ContentData.Contact.FK_Language) }).ToList();
            toReturn.Insert(0, new SelectListItem() { Value = "", Text = Resources.View_Register_SelectALanguage, Selected = toReturn.Select(x => x.Selected).Count() == 0 });
            return toReturn;
        }

        /// <summary>
        /// Gets the genres.
        /// </summary>
        /// <param name="_dataContext">The _data context.</param>
        /// <param name="language">The language.</param>
        /// <returns>List{SelectListItem}.</returns>
        private List<SelectListItem> GetGenres(DataRepositories _dataContext, string language)
        {
            List<Genre> dbGenres = _dataContext.Genre_Rep.GetAll().OrderBy(x => x.SortIndex).ToList();
            List<SelectListItem> toReturn = dbGenres.Select(x => new SelectListItem() { Value = x.Id.ToString(), Text = INNOVACALL.Framework.Common.MVCHelpers.Localization.CommonLocalization.LookupResource(typeof(Resources), x.Name), Selected = (x.Id == ContentData.Contact.FK_Genre) }).ToList();
            toReturn.Insert(0, new SelectListItem() { Value = "", Text = Resources.View_Register_SelectAGenre, Selected = toReturn.Select(x => x.Selected).Count() == 0 });
            return toReturn;
        }

        /// <summary>
        /// URL[Post]: /Register
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns>ActionResult.</returns>
        /// <exception cref="INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException"></exception>
        [HttpPost]
        public ActionResult Index(string language, Register_ViewModel model)
        {
            string Message = string.Empty;
            bool MailSent = false;

            StringBuilder oSB = new StringBuilder();
            oSB.AppendLine("User registration request");
            oSB.Append("from : ");
            oSB.AppendLine(this.HttpContext.Request.UserHostAddress);
            oSB.Append("Requested username : ");
            oSB.AppendLine(model.UserToRegister.Username);
            oSB.Append("with email : ");
            oSB.AppendLine(model.UserToRegister.Email);
            Logger.Info(enLog.Business, oSB.ToString());
            LandingPageSecurityParameters sendActivationEmailParameters = new LandingPageSecurityParameters();
            object eParameters = new { @model_Username = model.UserToRegister.Username };
            var currentMembershipAppName = Membership.ApplicationName;
            var currentRolesAppName = Roles.ApplicationName;
            //Création du compte utilisateur
            MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserToRegister.Username, model.UserToRegister.Password, model.UserToRegister.Email);
            if (createStatus == MembershipCreateStatus.Success)
            {
                using (TransactionScope _ts = new TransactionScope())
                {
                    try
                    {
                        using (DataRepositories _dataContext = new DataRepositories())
                        {
                            InnoAppUser currentUser = _dataContext.InnoAppUser_Rep.Query(x => x.InnoApplication.Name == currentMembershipAppName && x.Username == model.UserToRegister.Username).FirstOrDefault();
                            if (currentUser == null) throw new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethodBase + "Index[Post]", eParameters, Resources.ErrMsg_NewCreatedUserNotFound);
                            currentUser.Comment = model.UserToRegister.Comment;
                            //currentUser.CreationDate (déjà enregistré)
                            currentUser.Email = model.UserToRegister.Email;
                            currentUser.FailedPasswordAnswerAttemptCount = 0;
                            currentUser.FailedPasswordAnswerAttemptWindowStart = null;
                            currentUser.FailedPasswordAttemptCount = 0;
                            currentUser.FailedPasswordAttemptWindowStart = null;
                            _dataContext.Save();
                            Contact dbContact = new Contact();
                            dbContact.FirstName = model.Contact.FirstName;
                            dbContact.LastName = model.Contact.LastName;
                            dbContact.FK_Genre = model.Contact.FK_Genre;
                            dbContact.FK_Language = model.Contact.FK_Language;
                            dbContact.FK_InnoAppUser = currentUser.Id;
                            _dataContext.Contact_Rep.Add(dbContact);
                            _dataContext.Save();
                            sendActivationEmailParameters.userEMail = currentUser.Email;
                            sendActivationEmailParameters.userCreationDate = currentUser.CreationDate.ToString();
                            sendActivationEmailParameters.username = currentUser.Username;
                        }
                        _ts.Complete();
                        Message += "Transaction complete, user created but not activated\n";
                        Message += "Activation mail preparation starts\n";
                        MailSent = SendActivationEmail(sendActivationEmailParameters, ref Message);
                        oSB.AppendLine(Message);
                        Logger.Info(enLog.Business, oSB.ToString());
                    }
                    catch (Exception ex)
                    {
                        _ts.Dispose();
                        oSB.AppendLine("Unexpected error occurs");
                        oSB.AppendLine(ex.Message);
                        oSB.AppendLine(ex.StackTrace);
                        Message = oSB.ToString();
                        Logger.Info(enLog.Business, Message);
                        return Json(new { @success = MailSent, @message = Message, @scriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_ErrorDuringTransaction_Title.Replace("'", "\\'") + "','" + Resources.View_Register_ErrorDuringTransaction_Message.Replace("'", "\\'") + "');" });
                    }

                }
            }
            else
            {
                string FailureReason = base.ErrorCodeToString(createStatus);
                oSB.Append("Failure : ");
                oSB.AppendLine(FailureReason);
                Logger.Info(enLog.Business, oSB.ToString());
                return Json(new { @success = MailSent, @message = Message, @scriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_ErrorDuringTransaction_Title.Replace("'", "\\'") + "','" + FailureReason.Replace("'", "\\'") + "');" });
            }
            return Json(new { @success = MailSent, @message = Message, @scriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_Success_Title.Replace("'", "\\'") + "','" + Resources.View_Register_Success_Message.Replace("'", "\\'") + "','" + "/" + base.URLReferLanguage + "/LogOn');" });
        }

        /// <summary>
        /// Activation EMail sender
        /// </summary>
        /// <param name="sendActivationEmailParameters">The send activation email parameters.</param>
        /// <param name="logMessage">The log message.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        private bool SendActivationEmail(LandingPageSecurityParameters sendActivationEmailParameters, ref string logMessage)
        {
            bool toReturn = true;
            object eMethodParameters = new { @userEMail = sendActivationEmailParameters.userEMail, @userCreationDate = sendActivationEmailParameters.userCreationDate, @username = sendActivationEmailParameters.username };
            string landingPageAddress = string.Empty;
            string messageSubject = string.Format(Resources.View_Register_RegistrationActivationMail_Subject, this.SiteBaseURL);
            string messageBody = string.Empty;
            landingPageAddress = base.SendMailSecurizedLandingPageBuilder(enLandingPages.AccountActivation, base.URLReferLanguage, sendActivationEmailParameters.userEMail, sendActivationEmailParameters.userCreationDate);
            messageBody += Resources.View_Register_RegistrationActivationMail_Body1 + "\n<br/>";
            messageBody += "<a href=\"" + landingPageAddress + "\">" + Server.HtmlEncode(Resources.View_Register_ClickHereToRegister) + "</a><br/>";
            messageBody += Resources.View_Register_RegistrationActivationMail_Body2 + "\n<br/>";
            toReturn = base.SendMail(string.Empty, sendActivationEmailParameters.userEMail, sendActivationEmailParameters.username, messageSubject, true, messageBody);
            logMessage += "Activation mail sent\n";
            return toReturn;
        }
        #endregion
    }
}
